﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Linq;

namespace TIFPDFCounter
{
	public partial class MainForm : Form
	{
		const string pageStore = @"PageStore.xml";
		
		public MainForm()
		{
			InitializeComponent();
			MasterPageList = new List<PageSize>();
			LoadedFiles = new List<TPCFile>();
		}
		
		List<PageSize> MasterPageList { get; set; }
		List<PageCounter> PageCounters { get; set; }
		List<TPCFile> LoadedFiles { get; set; }
		
		protected override void OnDragEnter(DragEventArgs drgevent)
		{
			if (drgevent.Data.GetDataPresent(DataFormats.FileDrop))
				drgevent.Effect = DragDropEffects.Copy;
			base.OnDragEnter(drgevent);
		}
		
		public void CheckFileIsInList(string filename)
		{
			foreach (var tpcFile in LoadedFiles)
			{
				if (filename == tpcFile.FileName)
					throw new Exception("The file is already in the list.");
			}
		}
		
		string[] dropData;
		ProgressWindow progressWindow;
		protected override void OnDragDrop(DragEventArgs drgevent)
		{
			dropData = drgevent.Data.GetData(DataFormats.FileDrop) as string[];
			if (dropData == null || dropData.Length < 1)
				return;
			timer1.Enabled = true;
			timer1.Start();
			
		}
		
		void Timer1Tick(object sender, EventArgs e)
		{
			//timer1.Stop;
			timer1.Enabled = false;
			progressWindow = new ProgressWindow();
			progressWindow.BtnCancel.Click += delegate { fileWorker.CancelAsync(); };
			fileWorker.RunWorkerAsync(dropData);
			progressWindow.ShowDialog(this);
		}
		
		void FileWorkerDoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
		{
            var dropItems = e.Argument as string[];
            var worker = sender as System.ComponentModel.BackgroundWorker;
            var tpcFiles = new List<TPCFile>();
            var dropFiles = new List<string>();

            foreach (var dropItem in dropItems)
            {
                if (fileWorker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                try
                {
                    var attr = File.GetAttributes(dropItem);
                    if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
                        dropFiles.AddRange(Directory.EnumerateFiles(dropItem, "*.*", SearchOption.AllDirectories).OrderBy(x => x));
                    else
                        dropFiles.Add(dropItem);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                    var result = MessageBox.Show(dropItem + "\n\n" + ex.Message + "\n\nContinue loading other files?", "Problem", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
                    if (result == DialogResult.OK)
                        continue;

                    return;
                }
            }
            int i = 0;
            foreach (var dropFile in dropFiles)
            {
                if (fileWorker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                fileWorker.ReportProgress(++i * 100 / dropFiles.Count);
                TPCFile tpcFile = null;
                try
                {
                    CheckFileIsInList(dropFile);
                    tpcFile = TPCFile.Load(dropFile);
                    tpcFiles.Add(tpcFile);
                }
                catch (Exception ex)
                {
                    var result = MessageBox.Show(dropFile + "\n\n" + ex.Message + "\n\nContinue loading other files?", "Problem", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
                    if (result == DialogResult.OK)
                        continue;
                    e.Cancel = true;
                    return;
                }
            }
            e.Result = tpcFiles;
		}
		
		
		void FileWorkerProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
		{
			progressWindow.Progress = e.ProgressPercentage;
		}
		
		void FileWorkerRunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
		{
			progressWindow.Close();
			progressWindow.Dispose();
			if (e.Error != null)
			{
				MessageBox.Show(e.Error.Message);
			}
			else if (e.Cancelled)
			{
				Debug.WriteLine("Fileworker was cancelled");
				return;
			}
			else if (e.Result == null)
			{
				Debug.WriteLine("Fileworker result was null");
				return;
			}
			else
			{
				var tpcFiles = e.Result as List<TPCFile>;
                int totalPageCount = 0;
				foreach (var tpcFile in tpcFiles)
				{
                    totalPageCount += tpcFile.PageCount;
					string fileName = Path.GetFileName(tpcFile.FileName);
					for (int i = 0; i < tpcFile.PageCount; i++)
					{
						double width = Math.Round(tpcFile.Pages[i].Width, 2);
						double height = Math.Round(tpcFile.Pages[i].Height, 2);
						var size = string.Concat(width, " ", "\u00d7", " ", height);
						int rowIndex = dgvFilePages.Rows.Add(fileName, i + 1, tpcFile.Pages[i].ColorMode, size);
						dgvFilePages.Rows[rowIndex].Tag = tpcFile.Pages[i];
						fileName = null;
					}
				}
                
				LoadedFiles.AddRange(tpcFiles);
				DoPageSizeCount();
			}
		}
		
		void DoPageSizeCount()
		{
			dgvCounters.Rows.Clear();
			PageCounters = new List<PageCounter>();
			
			foreach (var pageSize in MasterPageList)
			{
				if (pageSize.Active)
					PageCounters.Add(new PageCounter(pageSize));
			}
			
			var unknownCounter = new PageCounter(null);
			
			foreach (DataGridViewRow dgvr in dgvFilePages.Rows)
			{
				var filePage = dgvr.Tag as TPCFilePage;
				
				bool match = false;
				foreach (var pageCounter in PageCounters)
				{
					if (pageCounter.PageSize.IsMatch(filePage.Width, filePage.Height))
					{
						pageCounter.AllPages.Add(filePage);
						match = true;
						break;
					}
				}
				if (!match)
				{
					unknownCounter.AllPages.Add(filePage);
				}
			}
			
			dgvCounters.Rows.Clear();
			PageCounters.Insert(0, unknownCounter);
			foreach (var pageCounter in PageCounters)
			{
				if (pageCounter.BWPages.Count > 0)
				{
					int rowIndex = dgvCounters.Rows.Add(pageCounter.Name, "BW", pageCounter.BWPages.Count);
					dgvCounters.Rows[rowIndex].Tag = pageCounter.BWPages;
				}
				if (pageCounter.ColorPages.Count > 0)
				{
					int rowIndex = dgvCounters.Rows.Add(pageCounter.Name, "Color", pageCounter.ColorPages.Count);
					dgvCounters.Rows[rowIndex].Tag = pageCounter.ColorPages;
				}
			}
            lblTotalFiles.Text = "Total Files: " + LoadedFiles.Count.ToString();
            int totalPageCount = 0;
            foreach (var file in LoadedFiles)
            {
                totalPageCount += file.PageCount;
            }
            lblTotalPages.Text = "Total Pages: " +  totalPageCount.ToString();
		}
		
		void MainFormFormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
		{
			Properties.Settings.Default.PDFColorTolerance = PDF.colorTolerance;
			if (WindowState == FormWindowState.Minimized)
				WindowState = FormWindowState.Normal;
			if (WindowState == FormWindowState.Normal)
			{
				Properties.Settings.Default.WindowState = (int)FormWindowState.Normal;
				Properties.Settings.Default.WindowPosition = Location;
				Properties.Settings.Default.WindowSize = Size;
			}
			if (WindowState == FormWindowState.Maximized)
				Properties.Settings.Default.WindowState = (int)FormWindowState.Maximized;
			
			Properties.Settings.Default.Save();
			
			var writer = new XmlSerializer(typeof(List<PageSize>));
			using (var fs = new FileStream(pageStore, FileMode.Truncate))
			{
				writer.Serialize(fs, MasterPageList);
			}
		}
		
		void MainFormLoad(object sender, System.EventArgs e)
		{
			PDF.colorTolerance = Properties.Settings.Default.PDFColorTolerance;
			Location = Properties.Settings.Default.WindowPosition;
			Size = Properties.Settings.Default.WindowSize;
			WindowState = (FormWindowState)Properties.Settings.Default.WindowState;
			
			var reader = new XmlSerializer(typeof(List<PageSize>));
			using (var fs = new FileStream(pageStore, FileMode.OpenOrCreate))
			{
				MasterPageList = reader.Deserialize(fs) as List<PageSize>;
			}
		}
		
		void BtnManageClick(object sender, EventArgs e)
		{
			using (var psm = new PageSizeManager(MasterPageList))
			{
				psm.ShowDialog(this);
				if (psm.DialogResult == DialogResult.OK)
				{
					MasterPageList.Clear();
					MasterPageList = psm.PageSizes;
				}
			}
			DoPageSizeCount();
		}
		void BtnClearListClick(object sender, EventArgs e)
		{
            lblTotalPages.Text = "Total Pages: 0";
            lblTotalFiles.Text = "Total Files: 0";
            lblSelected.Text = "Selected: 0";
			dgvFilePages.Rows.Clear();
			dgvCounters.Rows.Clear();
			LoadedFiles.Clear();
		}
		void HighlightPagesToolStripMenuItemClick(object sender, EventArgs e)
		{
			dgvFilePages.ClearSelection();
			foreach (DataGridViewRow counterRow in dgvCounters.SelectedRows)
			{
				var counterPages = counterRow.Tag as List<TPCFilePage>;
				foreach (var counterPage in counterPages)
				{
					foreach (DataGridViewRow row in dgvFilePages.Rows)
					{
						var filePage = row.Tag as TPCFilePage;
						if (filePage.Equals(counterPage))
							row.Selected = true;
					}
				}
			}
		}
		
		void DgvCountersMouseDown(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Right)
			{
				int rowIndex = dgvCounters.HitTest(e.X, e.Y).RowIndex;
                if (rowIndex == -1)
                    return;
				if (!dgvCounters.Rows[rowIndex].Selected)
				{
					dgvCounters.ClearSelection();
					dgvCounters.Rows[rowIndex].Selected = true;
				}
				ctxPages.Show(dgvCounters.PointToScreen(e.Location));
			}
		}
		
		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
		{
			switch (keyData)
			{
				case Keys.F1:
					
					return true;
				default:
					return base.ProcessCmdKey(ref msg, keyData);
			}
		}

        private void dgvFilePages_SelectionChanged(object sender, EventArgs e)
        {
            lblSelected.Text = "Selected: " + dgvFilePages.SelectedRows.Count;
        }

        private void btnSettings_Click(object sender, EventArgs e)
        {
            using (var settingsWindow = new Settings())
            {
                var result = settingsWindow.ShowDialog(this);
            }
        }
	}
}
